home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / vision / grafics / programm / ximgtool / ximgtool.c < prev    next >
C/C++ Source or Header  |  1995-11-25  |  10KB  |  374 lines

  1. /* XIMGTOOL - Tool for XIMG Level-1/2/3 files.
  2.  *          (c) 1995 by Guido Vollbeding.
  3.  *          Tested with Pure-C on Atari-TOS,
  4.  *          GNU-C on a SUN-SPARCstation,
  5.  *          and GNU-C on a Linux-Pentium-System.
  6.  *
  7.  * For Pure-C on TOS use the following project file:
  8.  *
  9.  * ximgtool.ttp
  10.  * =
  11.  * pcxstart.o
  12.  * ximgtool
  13.  * l3decode
  14.  * encoders
  15.  * pcstdlib.lib
  16.  * pctoslib.lib
  17.  *
  18.  * For GNU-C on UNIX use the following shell command:
  19.  *
  20.  * gcc -O -o ximgtool ximgtool.c l3decode.c encoders.c
  21.  *
  22.  * NOTE: The UNIX version does NOT support the -m
  23.  *       multiple mode option at the moment!
  24.  */
  25.  
  26. #ifdef __TOS__
  27. /* Change 0 to 1 if using tos.h */
  28. #if 0
  29. #include <tos.h>
  30. #else
  31. #include <osbind.h>
  32. #endif
  33. #else
  34. #include <fcntl.h>
  35. #include <unistd.h>
  36. #include <stdlib.h>
  37. #include <sys/stat.h>
  38. #define Fopen open
  39. #define Fclose close
  40. #define Fread(handle, count, buf) read(handle, buf, count)
  41. #define Fwrite(handle, count, buf) write(handle, buf, count)
  42. #define Fdelete unlink
  43. #define Malloc (void *(*)(long))malloc
  44. #define Mfree free
  45. #endif
  46.  
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <setjmp.h>
  50.  
  51. #include "imgcodec.h"
  52.  
  53. /* Forward declarations of local functions. */
  54.  
  55. static void ProcHeader(int ident);
  56.  
  57. static void do_proc(char *src, char *des, short outlev, short outpat, int ident);
  58.  
  59.  
  60. static jmp_buf jmp_buffer;
  61.  
  62.  
  63. /* The following stuff defines application specific file handling. */
  64.  
  65. #define BUF_LENGTH 80L*1024
  66.  
  67. typedef struct
  68. {
  69.   FBUFPUB pub;
  70.   long length;
  71.   int handle, EOF_flag;
  72.   /*
  73.    * Note: We simply use a static buffer of reasonable size here.
  74.    * Another implementation would hold a pointer to dynamically
  75.    * allocated buffer space here (plus size variable). In fact,
  76.    * the buffer size may be arbitrary, at least 1 Byte. This should
  77.    * work well with the given codecs, but would be very slow. It is
  78.    * recommended to use at least a couple of KBytes as reasonable
  79.    * buffer size. In dynamic case, using a buffer for full input
  80.    * file size is most efficient (only one buffer read hook).
  81.    */
  82.   char fbuf[BUF_LENGTH];
  83. }
  84. FBUF;
  85.  
  86. static void Fbufread(FBUF *fp)
  87. {
  88.   long count;
  89.  
  90.   if ((count = Fread(fp->handle, BUF_LENGTH, fp->fbuf)) > 0)
  91.   {
  92.     fp->length += count;
  93.     fp->pub.bytes_left += count;
  94.     fp->pub.pbuf = fp->fbuf;
  95.   }
  96.   else
  97.   {
  98.     fp->EOF_flag++;
  99.     /* Return to top level routine on short read. */
  100.     longjmp(jmp_buffer, 1);
  101. } }
  102.  
  103. static void Fbufwrite(FBUF *fp)
  104. {
  105.   long count;
  106.  
  107.   if ((count = BUF_LENGTH - fp->pub.bytes_left) != 0)
  108.   {
  109.     fp->length += count;
  110.     fp->pub.bytes_left += count;
  111.     fp->pub.pbuf = fp->fbuf;
  112.     if (fp->EOF_flag == 0)
  113.       if (Fwrite(fp->handle, count, fp->fbuf) != count)
  114.     fp->EOF_flag++;
  115. } }
  116.  
  117. static FBUF input;
  118. static FBUF output;
  119.  
  120. static short out_lev;
  121. static short out_pat;
  122.  
  123. static char inpath[128];
  124. static char outpath[128];
  125.  
  126. static IMG_HEADER header;
  127.  
  128. static void Usage(void)
  129. {
  130.   fprintf(stderr, "Usage:  ximgtool [options] input [output]\n");
  131.   fprintf(stderr, "options:\n");
  132.   fprintf(stderr, "\t-lN: Use Level-N encoding, N=1..3.\n");
  133.   fprintf(stderr, "\t     Default is input value cropped to 1..3.\n");
  134.   fprintf(stderr, "\t-pN: Force output pattern run N, N=1..2.\n");
  135.   fprintf(stderr, "\t     Default is input value cropped to 1..2.\n");
  136.   fprintf(stderr, "\t-i:  Identify only.\n");
  137. #ifdef __TOS__
  138.   fprintf(stderr, "\t-m:  Multiple mode.\n");
  139. #endif
  140.   fprintf(stderr, "input:\n");
  141.   fprintf(stderr, "\t(X)IMG source file"
  142. #ifdef __TOS__
  143.           " (pattern if -m)"
  144. #endif
  145.           ".\n");
  146.   fprintf(stderr, "output:\n");
  147.   fprintf(stderr, "\t(X)IMG destination file"
  148. #ifdef __TOS__
  149.           " (folder if -m)"
  150. #endif
  151.           ".\n");
  152. }
  153.  
  154. int main(int argc, char **argv)
  155. {
  156.   int ident, mult;
  157.   short outlev, outpat;
  158.   char *inname, *outname;
  159.  
  160.   fprintf(stdout,
  161.     "\nXIMGTOOL " __DATE__ " -- Tool for XIMG Level-1/2/3 files.\n\n");
  162.  
  163.   if (--argc <= 0) {
  164.     Usage(); return 0;
  165.   }
  166.   ++argv;
  167.  
  168.   ident = mult = 0; outlev = outpat = 0;
  169.   while (argv[0][0] == '-') {
  170.     if (argv[0][1] == 'l' || argv[0][1] == 'L') {
  171.       if (argv[0][2] == '1') outlev = 1;
  172.       else if (argv[0][2] == '2') outlev = 2;
  173.       else if (argv[0][2] == '3') outlev = 3;
  174.       else fprintf(stderr, "Ignoring invalid option %s\n", argv[0]);
  175.     }
  176.     else if (argv[0][1] == 'p' || argv[0][1] == 'P') {
  177.       if (argv[0][2] == '1') outpat = 1;
  178.       else if (argv[0][2] == '2') outpat = 2;
  179.       else fprintf(stderr, "Ignoring invalid option %s\n", argv[0]);
  180.     }
  181.     else if (argv[0][1] == 'i' || argv[0][1] == 'I') ident = 1;
  182. #ifdef __TOS__
  183.     else if (argv[0][1] == 'm' || argv[0][1] == 'M') mult = 1;
  184. #endif
  185.     else fprintf(stderr, "Ignoring invalid option %s\n", argv[0]);
  186.  
  187.     if (--argc <= 0) {
  188.       Usage(); return 0;
  189.     }
  190.     ++argv;
  191.   }
  192. #ifdef __TOS__
  193.   if (mult) {
  194.     static DTA mydta;
  195.     Fsetdta(&mydta);
  196.     if (Fsfirst(argv[0], 0x27)) {
  197.       fprintf(stderr, "Can't find matching file %s\n", argv[0]);
  198.       return 0;
  199.     }
  200.     strcpy(inpath, argv[0]);
  201.     inname = strrchr(inpath, '\\');
  202.     if (inname) inname++;
  203.     else {
  204.       inname = inpath;
  205.       if (inname[0] && inname[1] == ':')
  206.     inname += 2;
  207.     }
  208.     outname = 0;
  209.     if (argv[1]) {
  210.       outname = strcpy(outpath, argv[1]);
  211.       while (*outname++);
  212.       outname--;
  213.     }
  214.     do {
  215.       strcpy(inname, mydta.d_fname);
  216.       if (outname) {
  217.     strcpy(outname, mydta.d_fname);
  218.     do_proc(inpath, outpath, outlev, outpat, ident);
  219.       }
  220.       else do_proc(inpath, 0, outlev, outpat, ident);
  221.     }
  222.     while (Fsnext() == 0);
  223.   }
  224.   else
  225. #endif
  226.     do_proc(argv[0], argv[1], outlev, outpat, ident);
  227.   return 0;
  228. }
  229.  
  230. static void encode_exit(void)
  231. {
  232.   /* Return to top level routine if image end is reached. */
  233.   longjmp(jmp_buffer, 2);
  234. }
  235.  
  236. static void do_proc(char *src, char *des, short outlev, short outpat, int ident)
  237. {
  238.   IBUFPUB *image;
  239.   int error;
  240.  
  241.   out_lev = outlev; out_pat = outpat;
  242.  
  243.   if ((input.handle = Fopen(src, 0)) < 0) {
  244.     fprintf(stderr, "Can't open input file %s\n", src);
  245.     return;
  246.   }
  247.   input.EOF_flag = 0; input.length = 0;
  248.   input.pub.bytes_left = 0;
  249.   /* Note: pub.pbuf entry does not need to be set here. */
  250.   input.pub.data_func = (void (*)(FBUFPUB *))Fbufread;
  251.  
  252.   if (ident == 0) {
  253.     if (des == 0) {
  254.       output.handle = -1; output.EOF_flag = 1;
  255.     }
  256.     else {
  257. #ifdef __TOS__
  258.       if ((output.handle = Fcreate(des, 0)) < 0) {
  259. #else
  260.       static struct stat sbuf;
  261.       stat(src, &sbuf);
  262.       if ((output.handle = creat(des, sbuf.st_mode)) < 0) {
  263. #endif
  264.     fprintf(stderr, "Can't create output file %s\n", des);
  265.     Fclose(input.handle);
  266.     return;
  267.       }
  268.       output.EOF_flag = 0;
  269.     }
  270.     output.length = 0;
  271.     output.pub.bytes_left = sizeof(output.fbuf);
  272.     output.pub.pbuf = output.fbuf;
  273.     output.pub.data_func = (void (*)(FBUFPUB *))Fbufwrite;
  274.   }
  275.  
  276.   fprintf(stdout, "%s\n", src);
  277.   if (setjmp(jmp_buffer)) {
  278.     fprintf(stdout, "  is not a valid IMG file at all!\n");
  279.     if (ident == 0) {
  280.       if (output.handle >= 0) {
  281.     Fclose(output.handle); Fdelete(des);
  282.       }
  283.       ident = 1;
  284.     }
  285.   }
  286.   else {
  287.     ProcHeader(ident);
  288.     fprintf(stdout, "  is a %dx%d (X)IMG file with %ld colors (l=%d,p=%d).\n",
  289.         header.sl_width, header.sl_height, 1L << header.planes,
  290.         header.version, header.pat_run);
  291.     if (ident == 0) {
  292.       image = encode_init(&header, &output.pub,
  293.               Malloc, encode_exit,
  294.               out_lev, out_pat);
  295.       if (image == 0) {
  296.     fprintf(stderr, "  Insufficient memory!\n");
  297.     if (output.handle >= 0) {
  298.       Fclose(output.handle); Fdelete(des);
  299.     }
  300.     ident = 1;
  301.       }
  302.       else {
  303.     if (setjmp(jmp_buffer) == 0)
  304.  
  305.       /* OK, here's the real work... */
  306.       level_3_decode(&input.pub, image);
  307.  
  308.     /* Flush out last line(s) in case of short read break. */
  309.     (*image->put_line)(image);
  310.  
  311.     Mfree(image);
  312.     /* My, that was easy, wasn't it? */
  313.       }
  314.     }
  315.   }
  316.  
  317.   /* Done. Check for errors, print statistics... */
  318.   error = 0;
  319.   if (input.EOF_flag) {
  320.     error = 1;
  321.     fprintf(stderr,
  322.       "  Warning: Read Error or Premature EOF encountered in input stream!\n");
  323.   }
  324.   if (ident == 0) {
  325.     Fbufwrite(&output); /* Flush out last bytes from buffer. */
  326.     if (output.handle >= 0) {
  327.       if (output.EOF_flag) {
  328.     error = 1;
  329.     fprintf(stderr, "  Warning: Write Error occured in output file!\n");
  330.       }
  331.       if (Fclose(output.handle)) {
  332.     error = 1;
  333.     fprintf(stderr, "  Warning: Error in closing output file!\n");
  334.       }
  335.     }
  336.     if (error == 0) fprintf(stderr, "  Successful end of processing.\n");
  337.     fprintf(stdout, "  %ld input bytes, %ld output bytes, %ld saved bytes\n",
  338.         input.length, output.length, input.length - output.length);
  339.   }
  340.   Fclose(input.handle);
  341. }
  342.  
  343. static void ProcHeader(int ident)
  344. {
  345.   short save_l, save_p, temp, *p;
  346.   long count;
  347.  
  348.   p = (short *)&header; count = sizeof(header);
  349.   do { FGETW(&input.pub, temp); *p++ = temp; } while (count -= 2);
  350.   /*
  351.    * Sanity check. Po'bly to restrictive, but ensures
  352.    * reliability of actual code.
  353.    */
  354.   if (header.sl_width <= 0 ||
  355.       header.sl_height <= 0 ||
  356.       header.planes <= 0 ||
  357.       header.version < 0 ||
  358.       header.pat_run < 0) longjmp(jmp_buffer, 3);
  359.   if (ident == 0) {
  360.     save_l = header.version;
  361.     save_p = header.pat_run;
  362.     if (out_lev == 0) out_lev = save_l > 3 ? 3 : save_l < 1 ? 1 : save_l;
  363.     if (out_pat == 0) out_pat = save_p > 2 ? 2 : save_p < 1 ? 1 : save_p;
  364.     header.version = out_lev;
  365.     header.pat_run = out_pat;
  366.     p = (short *)&header; count = sizeof(header);
  367.     do { temp = *p++; FPUTW(&output.pub, temp); } while (count -= 2);
  368.     header.version = save_l;
  369.     header.pat_run = save_p;
  370.     count = ((long)header.headlen << 1) - sizeof(header);
  371.     while (--count >= 0) FCOPYC(&input.pub, &output.pub);
  372.   }
  373. }
  374.